﻿using System;
using System.Windows.Forms;

using Microsoft.Office.Tools.Ribbon;

using SharpSvn;

using OfficeSVN;


namespace WordSVN {

	public partial class SvnRibbon: OfficeRibbon {

        BaseOfficeSVN _BaseOfficeSVN = new BaseOfficeSVN();

        #region Constructor
        public SvnRibbon() {

			InitializeComponent();

            _BaseOfficeSVN.OpenDocumentEvent += new EventHandler<DocumentEventArgs>(OpenDocumentEvent);
            _BaseOfficeSVN.CloseDocumentEvent += new EventHandler<DocumentEventArgs>(CloseDocumentEvent);
            _BaseOfficeSVN.UpdateRibbonEvent += new EventHandler<UpdateRibbonEventArgs>(UpdateRibbonEvent);
            _BaseOfficeSVN.ReloadDocumentEvent += new EventHandler<DocumentEventArgs>(ReloadDocumentEvent);
        }

        #endregion

        private string CurrentDoc {
            get { return Globals.ThisAddIn.Application.ActiveDocument.FullName; }
        }

        #region Word events
        private void SvnRibbon_Load(object sender, RibbonUIEventArgs e) {
            Globals.ThisAddIn.Application.DocumentChange += new Microsoft.Office.Interop.Word.ApplicationEvents4_DocumentChangeEventHandler(Application_DocumentChange);
            Globals.ThisAddIn.Application.DocumentBeforeSave += new Microsoft.Office.Interop.Word.ApplicationEvents4_DocumentBeforeSaveEventHandler(Application_DocumentBeforeSave);
		}

        /// <summary>
        /// This is the man-in-the-middle-pattern :) 
        /// Because there is no event after a document was saved, I have to use this event. First, I save the document and after
        /// this, I´m able to update the ribbon.
        /// </summary>
        void Application_DocumentBeforeSave(Microsoft.Office.Interop.Word.Document Doc, ref bool SaveAsUI, ref bool Cancel) {

            // Do nothing, in case the document was never saved or should be saved as a new document.
            if (SaveAsUI)
                return;
            // 1) Save the document
            Doc.Save();
            // Globals.ThisAddIn.Application.ActiveDocument.Save();

            // 2) Set the cancel parameter to true to prvent Word for further saving the document.
            Cancel = true;

            // 3) Update the ribbon informations
            _BaseOfficeSVN.DocumentChanged(this.CurrentDoc);
        }

        void Application_DocumentChange() {
            _BaseOfficeSVN.DocumentChanged(this.CurrentDoc);
        }

        #endregion

        #region Button click events

        private void getLockButton_Click(object sender, RibbonControlEventArgs e) {

            _BaseOfficeSVN.GetLock(this.CurrentDoc);
        }

        private void releaseLockButton_Click(object sender, RibbonControlEventArgs e) {

            _BaseOfficeSVN.ReleaseLock(this.CurrentDoc);
        }

        private void commitButton_Click(object sender, RibbonControlEventArgs e) {

			// Ask to save the changes (if there are some unsaved changes)
			if (!Globals.ThisAddIn.Application.ActiveDocument.Saved) {
				switch (MessageBox.Show("There are unsafed changes. Do you want to save your changes?", "OfficeSVN", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)) {
					case DialogResult.Yes:
						Globals.ThisAddIn.Application.ActiveDocument.Save();
						break;
					case DialogResult.No:
						break;
					case DialogResult.Cancel:
						return;
				}
			}

            _BaseOfficeSVN.Commit(this.CurrentDoc, this.commentEditBox.Text);
        }

        private void updateButton_Click(object sender, RibbonControlEventArgs e) {

            _BaseOfficeSVN.Update(this.CurrentDoc);
        }

        private void revertButton_Click(object sender, RibbonControlEventArgs e) {

            // TODO: Check for changes and ask user...
            _BaseOfficeSVN.Revert(this.CurrentDoc);
        }

        private void addButton_Click(object sender, RibbonControlEventArgs e) {

            _BaseOfficeSVN.AddToSubversion(this.CurrentDoc);
        }
        #endregion

        #region OfficeSVN events
        void CloseDocumentEvent(object sender, DocumentEventArgs e) {

            Object Missing = System.Reflection.Missing.Value;
            Object ObjectIndex = System.Reflection.Missing.Value;

            for (int i = 1; i <= Globals.ThisAddIn.Application.Documents.Count; i++) {
                ObjectIndex = i;
                if (String.Compare(Globals.ThisAddIn.Application.Documents.get_Item(ref ObjectIndex).FullName, e.Document) == 0) {
                    Globals.ThisAddIn.Application.Documents.get_Item(ref ObjectIndex).Close(ref Missing, ref Missing, ref Missing);
                    return;
                }
            }
        }

        void OpenDocumentEvent(object sender, DocumentEventArgs e) {
            Object Missing = System.Reflection.Missing.Value;
            object CurrentDoc = e.Document;
            Globals.ThisAddIn.Application.Documents.Open(ref CurrentDoc, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing);
        }

        void UpdateRibbonEvent(object sender, UpdateRibbonEventArgs e) {

            // First, deactivate all controls
            this.addButton.Enabled = false;
            this.updateButton.Enabled = false;
            this.getLockButton.Enabled = false;
            this.releaseLockButton.Enabled = false;
            this.revertButton.Enabled = false;
            this.commitButton.Enabled = false;
            this.commentEditBox.Enabled = false;

            // Reset the information labels
            this.repositoryPathLabel.Label = "";
            this.revisionLabel.Label = "";
            this.statusLabel.Label = "Not versioned";

            if (e.Info.RepositoryPath != null)
                this.repositoryPathLabel.Label = e.Info.RepositoryPath.ToString();
            this.revisionLabel.Label = e.Info.Revision.ToString();
            this.statusLabel.Label = e.Info.Status.ToString();

            switch (e.Info.Status) {
                case SvnStatus.Zero:
                    this.statusLabel.Label = ""; // Looks better then "Zero"
                    break;

                case SvnStatus.NotVersioned:
                    this.addButton.Enabled = true;
                    break;

                case SvnStatus.Modified:
                    this.updateButton.Enabled = true;
                    this.commitButton.Enabled = true;
                    this.commentEditBox.Enabled = true;
                    this.revertButton.Enabled = true;
                    this.releaseLockButton.Enabled = e.Info.IsLocked;
                    break;

                case SvnStatus.Added:
                    this.statusLabel.Label = ""; // Looks better then "Zero"
                    this.commitButton.Enabled = true;
                    this.commentEditBox.Enabled = true;
                    this.revertButton.Enabled = true; // Better: UndoAddButton?
                    break;

                case SvnStatus.None:
                case SvnStatus.Normal:
                    this.updateButton.Enabled = true;
                    this.releaseLockButton.Enabled = e.Info.IsLocked;
                    this.getLockButton.Enabled = (e.Info.NeedsLock && !e.Info.IsLocked);
                    break;
            }
        }

        void ReloadDocumentEvent(object sender, DocumentEventArgs e) {
            Globals.ThisAddIn.Application.ActiveDocument.Reload();
        }
        #endregion
    }
}
